package tools

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"gorm.io/gorm/clause"
	"io"
	"io/ioutil"
	"mygo/app/models"
	"net/http"
	"os"
	"strconv"
	"sync"
	"time"
)

var (
	maxWorkers = 10
	semaphore  = make(chan struct{}, maxWorkers)
	wg         sync.WaitGroup
)

type Test struct {
	Time  string `json:"time" gorm:"primary_key;column:time"`
	Depth string `json:"depth" gorm:"column:depth"`
}

func AesEncrypt(orig string, key string) string {
	// 转成字节数组
	origData := []byte(orig)
	k := []byte(key)

	// 分组秘钥
	block, err := aes.NewCipher(k)
	if err != nil {
		panic(fmt.Sprintf("key 长度必须 16/24/32长度: %s", err.Error()))
	}
	// 获取秘钥块的长度
	blockSize := block.BlockSize()
	// 补全码
	origData = PKCS7Padding(origData, blockSize)
	// 加密模式
	blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
	// 创建数组
	cryted := make([]byte, len(origData))
	// 加密
	blockMode.CryptBlocks(cryted, origData)
	//使用RawURLEncoding 不要使用StdEncoding
	//不要使用StdEncoding  放在url参数中回导致错误
	return base64.RawURLEncoding.EncodeToString(cryted)

}

func AesDecrypt(cryted string, key string) string {
	//使用RawURLEncoding 不要使用StdEncoding
	//不要使用StdEncoding  放在url参数中回导致错误
	crytedByte, _ := base64.RawURLEncoding.DecodeString(cryted)
	k := []byte(key)

	// 分组秘钥
	block, err := aes.NewCipher(k)
	if err != nil {
		panic(fmt.Sprintf("key 长度必须 16/24/32长度: %s", err.Error()))
	}
	// 获取秘钥块的长度
	blockSize := block.BlockSize()
	// 加密模式
	blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
	// 创建数组
	orig := make([]byte, len(crytedByte))
	// 解密
	blockMode.CryptBlocks(orig, crytedByte)
	// 去补全码
	orig = PKCS7UnPadding(orig)
	return string(orig)
}

// 补码
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
	padding := blocksize - len(ciphertext)%blocksize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

// 去码
func PKCS7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

type Person struct {
	Name string
	Age  int
}

type ByAge []Person

func (a ByAge) Len() int      { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool {
	//	先按年龄排序再按名字长度排序
	if a[i].Age == a[j].Age {
		return len(a[i].Name) < len(a[j].Name)
	}
	return a[i].Age < a[j].Age
}

func dealChannel(ch any) {
	//	判断ch的类型
	switch ch.(type) {
	case chan int:
		fmt.Println("int")
	case chan string:
		fmt.Println("string")
	}
}

//var ForeMap = map[string][]byte{
//	"hy": nil,
//	"hx": nil,
//	"df": nil,
//}

var tableList = []any{
	models.ForeList{},
	models.ForeDetailJson{},
	models.TwcTide{},
	models.RaForeOne{},
	models.SaForeOne{},
	models.YyFore{},
}

func Ceshi() {
	//79bc458c262cbebeb94094dfcee37bf5
	//打印解密后的数据
	//key := "91234567890123456789012345678901"
	//fmt.Println(AesEncrypt("123456", key))
	//GetSeaTemp()
	//fmt.Println(ReplaceNum("6-7▽8，大后天傍晚减小到4-5▽6"))
	//fmt.Println(ModifyWindSpeed("8-9", "1"))
	//fmt.Println(ReplaceFloat64("1.5米，明天傍晚减小到12.2米", []float64{1.9, 111.6}))
	//时间戳1702621813转为标准时间
	//获取当前10位时间戳
	//now := time.Now().Unix()
	//now = 1609397617
	////key是now的前8位
	//key := []byte(strconv.FormatInt(now, 10)[:8])
	//fmt.Println(strconv.FormatInt(now, 10)[:8])
	//str := []byte("testItf")
	//desByte, _ := DesEncrypt(str, key)
	//dataStr := base64.StdEncoding.EncodeToString(desByte)
	//fmt.Println(dataStr)
	//
	//md5Byte := MD5([]byte("1234567890"))
	//md5Str := base64.StdEncoding.EncodeToString(md5Byte)
	//fmt.Println(md5Str)
	//_ = models.Db.AutoMigrate(&models.AlarmType{})
	//_ = models.Db.AutoMigrate(&models.MessageSend{})

	//fmt.Println(FormatTime("1702621813"))
	//PostTest()1702621813
	_ = models.Db.AutoMigrate(&models.TideHourNew{})
	//_ = models.Db.AutoMigrate(&models.Condition{})
	//_ = models.Db.AutoMigrate(&models.AlarmDetail{})

	//_ = models.Db.AutoMigrate(models.AlarmDetail{})
	//_ = models.Db.AutoMigrate(&models.TideHour{})
	//for _, v := range tableList {
	//	models.Db.AutoMigrate(v)
	//}
	//var detailList []models.ForeDetail
	//models.Db.Find(&detailList)
	//for _, v := range detailList {
	//	if v.Time != "-1" {
	//		jsonName := "./public/yubao/" + v.Data + ".json"
	//		file, _ := os.ReadFile(jsonName)
	//		decoder := simplifiedchinese.GBK.NewDecoder()
	//		file, _ = decoder.Bytes(file)
	//		var forecast = models.Forecast{}
	//		json.Unmarshal(file, &forecast)
	//		var foreDetailJson models.ForeDetailJson
	//		foreDetailJson.ForeListId = v.ForeListId
	//		foreDetailJson.Time = v.Time
	//		foreDetailJson.State = v.State
	//		foreDetailJson.FileName = v.FileName
	//		data, _ := json.Marshal(forecast)
	//		foreDetailJson.Data = data
	//	}
	//}

	_ = models.Db.AutoMigrate(&models.TideHourNew{})
	//_ = models.Db.AutoMigrate(&models.ForeDetailJson{})
	//_ = models.Db.AutoMigrate(&models.Tf{})
	//_ = models.Db.AutoMigrate(&models.RaForeOne{})
	//var foreDetail []models.ForeDetail
	//models.Db.Find(&foreDetail)
	//for _, v := range foreDetail {
	//	if v.Time == "-1" {
	//		continue
	//	}
	//	jsonName := "./public/yubao/" + v.Data + ".json"
	//	file, _ := os.ReadFile(jsonName)
	//	decoder := simplifiedchinese.GBK.NewDecoder()
	//	file, _ = decoder.Bytes(file)
	//	foreDetailJson := models.ForeDetailJson{
	//		Data:       file,
	//		Time:       v.Time,
	//		ForeListId: v.ForeListId,
	//		State:      v.State,
	//		FileName:   v.FileName,
	//	}
	//	models.Db.Save(&foreDetailJson)
	//}
	//var foreList []models.ForeList
	//models.Db.Find(&foreList)
	//for _, v := range foreList {
	//	jsonName := "./public/yubaotemp/" + v.Code + ".json"
	//	file, _ := os.ReadFile(jsonName)
	//	decoder := simplifiedchinese.GBK.NewDecoder()
	//	file, _ = decoder.Bytes(file)
	//	v.Data = datatypes.JSON(file)
	//	models.Db.Save(&v)
	//}
	//遍历foreMap
	//for k, _ := range ForeMap {
	//	jsonName := "./public/yubaotemp/" + k + ".json"
	//	file, _ := os.ReadFile(jsonName)
	//	decoder := simplifiedchinese.GBK.NewDecoder()
	//	file, _ = decoder.Bytes(file)
	//	ForeMap[k] = file
	//}
	//_ = models.Db.AutoMigrate(&models.ForeDetailJson{})
	//type One struct {
	//	BaseModel
	//	Data datatypes.JSON `json:"data" gorm:"column:data"`
	//}
	//var one models.One
	//one.Data = datatypes.JSON([]byte(`{"name":"张三","age":18}`))
	//models.Db.Create(&one)
	//handleRequest := func() {
	//	fmt.Println("处理请求")
	//	// 模拟请求处理逻辑
	//	// ...
	//}
	//for i := 0; i < 100; i++ {
	//	wg.Add(1)
	//	go func() {
	//		semaphore <- struct{}{} // 获取信号量
	//		handleRequest()         // 调用接口处理函数
	//		<-semaphore             // 释放信号量
	//		wg.Done()
	//	}()
	//}
	//
	//wg.Wait() // 等待所有请求处理完成
	//清空models.TwcTide
	//models.Db.Exec("truncate table twc_tide")
	//
	//_ = models.Db.AutoMigrate(&models.AlarmType{})
	//_ = models.Db.AutoMigrate(&models.TwcTide{})
	//表变化
	//_ = models.Db.AutoMigrate(&models.ForeDetail{})
	//_ = models.Db.AutoMigrate(&models.AlarmList{})
	//_ = models.Db.AutoMigrate(&models.AlarmDetail{})
	////警报发送配置
	//strArr := []string{"wz"}
	//for _, v := range strArr {
	//	var alarmLists []models.AlarmList
	//	models.Db.Where("region = ?", "qt").Find(&alarmLists)
	//	for _, alarmList := range alarmLists {
	//		alarmList.Region = v
	//		alarmList.Id = 0
	//		models.Db.Create(&alarmList)
	//	}
	//}
	////警报详情
	//var alarmDetails []models.AlarmDetail
	//models.Db.Find(&alarmDetails)
	//for _, alarmList := range alarmDetails {
	//	alarmList.Region = "qt"
	//	models.Db.Save(&alarmList)
	//}

	//processes, err := ps.Processes()
	//if err != nil {
	//	panic(err)
	//}
	//for _, p := range processes {
	//	fmt.Printf("%d\t%s\n", p.Pid(), p.Executable())
	//}
	//
	//bounds := image.Rect(0, 0, 800, 600)
	//img, err := screenshot.CaptureRect(bounds)
	//if err != nil {
	//	panic(err)
	//}
	//file, _ := os.Create("test.png")
	//
	//defer file.Close()
	//
	//err = png.Encode(file, img)
	//if err != nil {
	//	panic(err)
	//}
}

func CopyFile(file string, path string) {
	//打开文件
	srcFile, err := os.Open(file)
	if err != nil {
		fmt.Println("打开文件失败")
		return
	}
	defer srcFile.Close()
	//创建新文件
	newFile, err := os.Create(path)
	if err != nil {
		fmt.Println("创建新文件失败")
		return
	}
	defer newFile.Close()
	//将源文件内容写入新文件
	_, err = io.Copy(newFile, srcFile)
	if err != nil {
		fmt.Println("复制文件失败")
		return
	}
}

func GetFileList(path string) (interface{}, interface{}) {
	var fileList []models.FileList
	//获取文件列表
	models.Db.Model(&models.FileList{}).Select("id, file_name, file_path, file_type, file_size, file_time").Find(&fileList)
	//获取文件列表总数
	var count int64
	models.Db.Model(&models.FileList{}).Count(&count)
	return fileList, count
}

//	func PKCS5Padding(data []byte, blockSize int) []byte {
//		padding := blockSize - len(data)%blockSize
//		padtext := bytes.Repeat([]byte{byte(padding)}, padding)
//		return append(data, padtext...)
//	}
func movingAvg(data []float64, window int) []float64 {
	ma := make([]float64, len(data))
	for i := 0; i < len(data); i++ {
		sum := 0.0
		for j := 0; j < window && i-j >= 0; j++ {
			sum += data[i-j]
		}
		ma[i] = sum / float64(window)
	}
	return ma
}

// 寻找平滑曲线上的局部极大极小值
func localExtrema(data []float64) ([]int, []int) {
	maxIdxs := []int{}
	minIdxs := []int{}

	for i := 1; i < len(data)-1; i++ {
		if data[i] > data[i-1] && data[i] > data[i+1] {
			maxIdxs = append(maxIdxs, i)
		}
		if data[i] < data[i-1] && data[i] < data[i+1] {
			minIdxs = append(minIdxs, i)
		}
	}

	return maxIdxs, minIdxs
}
func putData(channel chan Test, rows [][]string, sheetName string) {
	//defer wg.Done()
	//currentRow := 3
	//numOffset := "0"
	for index, row := range rows {
		if index > 2 {
			var test Test
			test.Time = row[0]
			test.Depth = row[3]
			channel <- test
		}
	}
	close(channel)
	wg.Done()
}
func saveData(channel chan Test) {
	defer wg.Done()
	var testList []Test
	for test := range channel {
		//models.Db.Clauses(clause.OnConflict{
		//	Columns:   []clause.Column{{Name: "time"}},
		//	DoUpdates: clause.AssignmentColumns([]string{"depth"}),
		//}).Create(&test)
		//	每100条数据提交一次
		testList = append(testList, test)
		if len(testList) == 1000 {
			models.Db.Clauses(clause.OnConflict{
				Columns:   []clause.Column{{Name: "time"}},
				DoUpdates: clause.AssignmentColumns([]string{"depth"}),
			}).Create(&testList)
			testList = nil
		}
	}
}

//func GetTf() {
//	//清空tf表,逐个删除
//	var oldTfs []models.Tf
//	models.Db.Find(&oldTfs)
//	for _, v := range oldTfs {
//		models.Db.Delete(&v)
//	}
//// http.Get("https://tf.istrongcloud.com/data/complex/2024.json") 将2024改成实时获取本年度 去请求json
//    // var year int = 2024
//
//
//
//
//	resp, err1 := http.Get("https://tf.istrongcloud.com/data/complex/2025.json")
//	if err1 != nil {
//		fmt.Println(err1)
//	}
//	defer resp.Body.Close()
//	// 读取响应内容
//	body, err1 := ioutil.ReadAll(resp.Body)
//	if err1 != nil {
//		fmt.Println(err1)
//		return
//	}
//	var tfs []models.Tf
//	json.Unmarshal(body, &tfs)
//	for idx, v := range tfs {
//		if (v.IsCurrent == 1 && v.Tfbh == v.Ident) || idx == 1 {
//			models.Db.Create(&v)
//		}
//	}
//}

func GetTf() {
	// 清空tf表,逐个删除
	var oldTfs []models.Tf
	models.Db.Find(&oldTfs)
	for _, v := range oldTfs {
		models.Db.Delete(&v)
	}

	// 获取当前年份（动态）
	currentYear := time.Now().Year()
	url := fmt.Sprintf("https://tf.istrongcloud.com/data/complex/%d.json", currentYear)

	resp, err1 := http.Get(url)
	if err1 != nil {
		fmt.Println(err1)
		return // 添加return避免后续操作
	}
	defer resp.Body.Close()

	// 读取响应内容
	body, err1 := io.ReadAll(resp.Body) // 注意：ioutil.ReadAll在Go 1.16+已被弃用
	if err1 != nil {
		fmt.Println(err1)
		return
	}

	var tfs []models.Tf
	if err := json.Unmarshal(body, &tfs); err != nil {
		fmt.Println("JSON unmarshal error:", err)
		return
	}

	for idx, v := range tfs {
		if (v.IsCurrent == 1 && v.Tfbh == v.Ident) || idx == 1 {
			models.Db.Create(&v)
		}
	}
}

func PostTest() {
	//resp, _ := http.Post("http://sss", "application/json", bytes.NewBuffer([]byte(`{"name":"张三","age":18}`)))
	//resp.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	//resp.Header.Add("ContentLength", "bytes.Length.ToString()")https://www.wzhy.com.cn:9005/wz/getForeDetailLast

	req, err := http.NewRequest("POST", "https://www.wzhy.com.cn:9005/test", bytes.NewBuffer([]byte(`{"name":"张三","age":18}`)))
	if err != nil {
		// 处理错误
	}

	req.Header.Set("Content-Type", "application/json")
	contentLength := strconv.Itoa(100)
	req.Header.Set("Content-Length", contentLength)

	client := http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		// 处理错误
	}
	defer resp.Body.Close()

	// 读取响应内容
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// 处理错误
	}
	fmt.Println(string(body))
}
